/*!
 * @file        apm32f4xx_eth.c
 *
 * @brief       This file provides all the ETH firmware functions
 *
 * @version     V1.0.1
 *
 * @date        2022-02-25
 *
 * @attention
 *
 *  Copyright (C) 2021-2022 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be usefull and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

#ifndef __APM32F4xx_ETH_H
#define __APM32F4xx_ETH_H

#ifdef __cplusplus
  extern "C" {
#endif

#include "apm32f4xx.h"

/** @addtogroup Peripherals_Library Standard Peripheral Library
  @{
*/

/** @addtogroup ETH_Driver ETH Driver
  @{
*/

/** @addtogroup ETH_Enumerations Enumerations
  @{
*/

/**
 * @brief    ETH AutoNegotiation
 */
typedef enum
{
    ETH_AUTONEGOTIATION_DISABLE,
    ETH_AUTONEGOTIATION_ENABLE
}ETH_AUTONEGOTIATION_T;

/**
 * @brief    ETH Watchdog
 */
typedef enum
{
    ETH_WATCHDOG_ENABLE,
    ETH_WATCHDOG_DISABLE
}ETH_WATCHDOG_T;

/**
 * @brief    ETH Jabber
 */
typedef enum
{
    ETH_JABBER_ENABLE,
    ETH_JABBER_DISABLE
}ETH_JABBER_T;

/**
 * @brief    ETH Inter Frame Gap
 */
typedef enum
{
    ETH_INTERFRAMEGAP_96BIT = 0x00,
    ETH_INTERFRAMEGAP_88BIT = 0x01,
    ETH_INTERFRAMEGAP_80BIT = 0x02,
    ETH_INTERFRAMEGAP_72BIT = 0x03,
    ETH_INTERFRAMEGAP_64BIT = 0x04,
    ETH_INTERFRAMEGAP_56BIT = 0x05,
    ETH_INTERFRAMEGAP_48BIT = 0x06,
    ETH_INTERFRAMEGAP_40BIT = 0x07
}ETH_INTERFRAMEGAP_T;

/**
 * @brief    ETH Carrier Sense
 */
typedef enum
{
    ETH_CARRIERSENCE_ENABLE,
    ETH_CARRIERSENCE_DISABLE
}ETH_CARRIERSENCE_T;

/**
 * @brief    ETH Speed
 */
typedef enum
{
    ETH_SPEED_10M,
    ETH_SPEED_100M
}ETH_SPEED_T;

/**
 * @brief    ETH Receive Own
 */
typedef enum
{
    ETH_RECEIVEOWN_ENABLE,
    ETH_RECEIVEOWN_DISABLE
}ETH_RECEIVEOWN_T;

/**
 * @brief    ETH Loop Back Mode
 */
typedef enum
{
    ETH_LOOPBACKMODE_DISABLE,
    ETH_LOOPBACKMODE_ENABLE
}ETH_LOOPBACKMODE_T;

/**
 * @brief    ETH Duplex Mode
 */
typedef enum
{
    ETH_MODE_HALFDUPLEX,
    ETH_MODE_FULLDUPLEX
}ETH_MODE_T;

/**
 * @brief    ETH Checksum Offload
 */
typedef enum
{
    ETH_CHECKSUMOFFLAOD_DISABLE,
    ETH_CHECKSUMOFFLAOD_ENABLE
}ETH_CHECKSUMOFFLAOD_T;

/**
 * @brief    ETH Retry Transmission
 */
typedef enum
{
    ETH_RETRYTRANSMISSION_ENABLE,
    ETH_RETRYTRANSMISSION_DISABLE
}ETH_RETRYTRANSMISSION_T;

/**
 * @brief    ETH Automatic Pad CRC Strip
 */
typedef enum
{
    ETH_AUTOMATICPADCRCSTRIP_DISABLE,
    ETH_AUTOMATICPADCRCSTRIP_ENABLE
}ETH_AUTOMATICPADCRCSTRIP_T;

/**
 * @brief    ETH Back Off Limit
 */
typedef enum
{
    ETH_BACKOFFLIMIT_10,
    ETH_BACKOFFLIMIT_8,
    ETH_BACKOFFLIMIT_4,
    ETH_BACKOFFLIMIT_1
}ETH_BACKOFFLIMIT_T;

/**
 * @brief    ETH Deferral Check
 */
typedef enum
{
    ETH_DEFFERRALCHECK_DISABLE,
    ETH_DEFFERRALCHECK_ENABLE
}ETH_DEFFERRALCHECK_T;

/**
 * @brief    ETH Receive All
 */
typedef enum
{
    ETH_RECEIVEAll_DISABLE,
    ETH_RECEIVEALL_ENABLE
}ETH_RECEIVEAll_T;

/**
 * @brief    ETH Source Addr Filter
 */
typedef enum
{
    ETH_SOURCEADDRFILTER_DISABLE,
    ETH_SOURCEADDRFILTER_NORMAL_ENABLE = BIT9,
    ETH_SOURCEADDRFILTER_INVERSE_ENABLE = BIT8|BIT9,
}ETH_SOURCEADDRFILTER_T;

/**
 * @brief    ETH Pass Control Frames
 */
typedef enum
{
    ETH_PASSCONTROLFRAMES_BLOCKALL = 1,
    ETH_PASSCONTROLFRAMES_FORWARDALL,
    ETH_PASSCONTROLFRAMES_FORWARDPASSEDADDRFILTER
}ETH_PASSCONTROLFRAMES_T;

/**
 * @brief    ETH Broadcast Frames Reception
 */
typedef enum
{
    ETH_BROADCASTFRAMESRECEPTION_ENABLE,
    ETH_BROADCASTFRAMESRECEPTION_DISABLE
}ETH_BROADCASTFRAMESRECEPTION_T;

/**
 * @brief    ETH Destination Addr Filter
 */
typedef enum
{
    ETH_DESTINATIONADDRFILTER_NORMAL,
    ETH_DESTINATIONADDRFILTER_INVERSE
}ETH_DESTINATIONADDRFILTER_T;

/**
 * @brief    ETH Destination Addr Filter
 */
typedef enum
{
    ETH_PROMISCUOUS_MODE_DISABLE,
    ETH_PROMISCUOUS_MODE_ENABLE
}ETH_PROMISCUOUS_MODE_T;

/**
 * @brief    ETH Multicast Frames Filter
 */
typedef enum
{
    ETH_MULTICASTFRAMESFILTER_PERFECT,
    ETH_MULTICASTFRAMESFILTER_NONE = BIT4,
    ETH_MULTICASTFRAMESFILTER_HASHTABLE = BIT2,
    ETH_MULTICASTFRAMESFILTER_PERFECTHASHTABLE = BIT2|BIT10
}ETH_MULTICASTFRAMESFILTER_T;

/**
 * @brief    ETH Unicast Frames Filter
 */
typedef enum
{
    ETH_UNICASTFRAMESFILTER_PERFECT,
    ETH_UNICASTFRAMESFILTER_HASHTABLE = BIT1,
    ETH_UNICASTFRAMESFILTER_PERFECTHASHTABLE = BIT1|BIT10
}ETH_UNICASTFRAMESFILTER_T;

/**
 * @brief    ETH Zero Quanta Pause
 */
typedef enum
{
    ETH_ZEROQUANTAPAUSE_ENABLE,
    ETH_ZEROQUANTAPAUSE_DISABLE
}ETH_ZEROQUANTAPAUSE_T;

/**
 * @brief    ETH Pause Low Threshold
 */
typedef enum
{
    ETH_PAUSELOWTHRESHOLD_MINUS4,
    ETH_PAUSELOWTHRESHOLD_MINUS28,
    ETH_PAUSELOWTHRESHOLD_MINUS144,
    ETH_PAUSELOWTHRESHOLD_MINUS256
}ETH_PAUSELOWTHRESHOLD_T;

/**
 * @brief    ETH Unicast Pause Frame Detect
 */
typedef enum
{
    ETH_UNICASTPAUSEFRAMEDETECT_DISABLE,
    ETH_UNICASTPAUSEFRAMEDETECT_ENABLE
}ETH_UNICASTPAUSEFRAMEDETECT_T;

/**
 * @brief    ETH Receive Flow Control
 */
typedef enum
{
    ETH_RECEIVEFLOWCONTROL_DISABLE,
    ETH_RECEIVEFLOWCONTROL_ENABLE
}ETH_RECEIVEFLOWCONTROL_T;

/**
 * @brief    ETH Transmit Flow Control
 */
typedef enum
{
    ETH_TRANSMITFLOWCONTROL_DISABLE,
    ETH_TRANSMITFLOWCONTROL_ENABLE
}ETH_TRANSMITFLOWCONTROL_T;

/**
 * @brief    ETH VLAN Tag Comparison
 */
typedef enum
{
    ETH_VLANTAGCOMPARISON_16BIT,
    ETH_VLANTAGCOMPARISON_12BIT
}ETH_VLANTAGCOMPARISON_T;

/**
 * @brief    ETH MAC Flags
 */
typedef enum
{
    ETH_MAC_FLAG_TST  = 0x00000200,
    ETH_MAC_FLAG_MMCT = 0x00000040,
    ETH_MAC_FLAG_MMCR = 0x00000020,
    ETH_MAC_FLAG_MMC  = 0x00000010,
    ETH_MAC_FLAG_PMT  = 0x00000008
}ETH_MAC_FLAG_T;

/**
 * @brief    ETH MAC Interrupts
 */
typedef enum
{
    ETH_MAC_INT_TST  = 0x00000200,
    ETH_MAC_INT_MMCT = 0x00000040,
    ETH_MAC_INT_MMCR = 0x00000020,
    ETH_MAC_INT_MMC  = 0x00000010,
    ETH_MAC_INT_PMT  = 0x00000008
}ETH_MAC_INT_T;

/**
 * @brief    ETH MAC Interrupts
 */
typedef enum
{
    ETH_MAC_ADDRESS0 = 0x00000000,
    ETH_MAC_ADDRESS1 = 0x00000008,
    ETH_MAC_ADDRESS2 = 0x00000010,
    ETH_MAC_ADDRESS3 = 0x00000018
}ETH_MAC_ADDRESS_T;

/**
 * @brief    ETH MAC addresses filter SA/DA
 */
typedef enum
{
    ETH_MAC_ADDRESSFILTER_SA,
    ETH_MAC_ADDRESSFILTER_DA = BIT30
}ETH_MAC_ADDRESSFILTER_T;

/**
 * @brief    ETH MAC addresses filter Mask bytes
 */
typedef enum
{
    ETH_MAC_ADDRESSMASK_BYTE6 = 0x20000000,  //!< Mask MAC Address high reg bits [15:8]
    ETH_MAC_ADDRESSMASK_BYTE5 = 0x10000000,  //!< Mask MAC Address high reg bits [7:0]
    ETH_MAC_ADDRESSMASK_BYTE4 = 0x08000000,  //!< Mask MAC Address low reg bits [31:24]
    ETH_MAC_ADDRESSMASK_BYTE3 = 0x04000000,  //!< Mask MAC Address low reg bits [23:16]
    ETH_MAC_ADDRESSMASK_BYTE2 = 0x02000000,  //!< Mask MAC Address low reg bits [15:8]
    ETH_MAC_ADDRESSMASK_BYTE1 = 0x01000000   //!< Mask MAC Address low reg bits [70]
}ETH_MAC_ADDRESSMASK_T;

/**
 * @brief    DMA Tx descriptor flags
 */
typedef enum
{
    ETH_DMATXDESC_OWN      = (int)0x80000000,
    ETH_DMATXDESC_INTC     = 0x40000000,
    ETH_DMATXDESC_LS       = 0x20000000,
    ETH_DMATXDESC_FS       = 0x10000000,
    ETH_DMATXDESC_DISC     = 0x08000000,
    ETH_DMATXDESC_DISP     = 0x04000000,
    ETH_DMATXDESC_TXTSEN   = 0x02000000,
    ETH_DMATXDESC_TXENDR   = 0x00200000,
    ETH_DMATXDESC_TXCH     = 0x00100000,
    ETH_DMATXDESC_TXTSS    = 0x00020000,
    ETH_DMATXDESC_IHERR    = 0x00010000,
    ETH_DMATXDESC_ERRS     = 0x00008000,
    ETH_DMATXDESC_JTO      = 0x00004000,
    ETH_DMATXDESC_FF       = 0x00002000,
    ETH_DMATXDESC_IPERR    = 0x00001000,
    ETH_DMATXDESC_LSC      = 0x00000800,
    ETH_DMATXDESC_NC       = 0x00000400,
    ETH_DMATXDESC_LC       = 0x00000200,
    ETH_DMATXDESC_EC       = 0x00000100,
    ETH_DMATXDESC_VLANF    = 0x00000080,
    ETH_DMATXDESC_CCNT     = 0x00000078,
    ETH_DMATXDESC_EDEF     = 0x00000004,
    ETH_DMATXDESC_UFERR    = 0x00000002,
    ETH_DMATXDESC_DEF      = 0x00000001
}ETH_DMATXDESC_FLAG_T;

/**
 * @brief    ETH DMA Tx descriptor segment
 */
typedef enum
{
    ETH_DMATXDESC_LASTSEGMENTS = BIT30,
    ETH_DMATXDESC_FIRSTSEGMENT = BIT29
}ETH_DMATXDESC_SEGMENTS_T;

/**
 * @brief    ETH DMA Tx descriptor Checksum Insertion Control
 */
typedef enum
{
    ETH_DMATXDESC_CHECKSUMBYPASS,
    ETH_DMATXDESC_CHECKSUMIPV4HEADER = BIT22,
    ETH_DMATXDESC_CHECKSUMTCPUDPICMPSEGMENT = BIT23,
    ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL = BIT22|BIT23
}ETH_DMATXDESC_CHECKSUMB_T;

/**
 * @brief    DMA Rx descriptor status
 */
typedef enum
{
    ETH_DMARXDESC_OWN      =  (int)0x80000000U,
    ETH_DMARXDESC_ADDRF    =  0x40000000,
    ETH_DMARXDESC_ERRS     =  0x00008000,
    ETH_DMARXDESC_DESERR   =  0x00004000,
    ETH_DMARXDESC_SADDRF   =  0x00002000,
    ETH_DMARXDESC_LERR     =  0x00001000,
    ETH_DMARXDESC_OFERR    =  0x00000800,
    ETH_DMARXDESC_VLANF    =  0x00000400,
    ETH_DMARXDESC_FDES     =  0x00000200,
    ETH_DMARXDESC_LDES     =  0x00000100,
    ETH_DMARXDESC_IPV4HCE  =  0x00000080,
    ETH_DMARXDESC_LC       =  0x00000040,
    ETH_DMARXDESC_FT       =  0x00000020,
    ETH_DMARXDESC_RXWDTTO  =  0x00000010,
    ETH_DMARXDESC_RERR     =  0x00000008,
    ETH_DMARXDESC_DERR     =  0x00000004,
    ETH_DMARXDESC_CERR     =  0x00000002,
    ETH_DMARXDESC_MAMPCE   =  0x00000001
}ETH_DMARXDESC_FLAG_T;

/**
 * @brief    DMA Rx descriptor extended flags
 */
typedef enum
{
    ETH_DMAPTPRXDESC_PTPV   =  0x00002000,
    ETH_DMAPTPRXDESC_PTPFT  =  0x00001000,
    ETH_DMAPTPRXDESC_PTPMT  =  0x00000F00,
    ETH_DMAPTPRXDESC_IPV6P  =  0x00000080,
    ETH_DMAPTPRXDESC_IPV4P  =  0x00000040,
    ETH_DMAPTPRXDESC_IPCBP  =  0x00000020,
    ETH_DMAPTPRXDESC_IPPERR =  0x00000010,
    ETH_DMAPTPRXDESC_IPHERR =  0x00000008,
    ETH_DMAPTPRXDESC_IPPT   =  0x00000007
}ETH_DMAPTPRXDESC_FLAG_T;

/**
 * @brief    ETH DMA Rx descriptor buffers
 */
typedef enum
{
    ETH_DMARXDESC_BUFFER1,
    ETH_DMARXDESC_BUFFER2
}ETH_DMARXDESC_BUFFER_T;

/**
 * @brief    ETH Drop TCP IP Checksum Error Frame
 */
typedef enum
{
    ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE,
    ETH_DROPTCPIPCHECKSUMERRORFRAME_DISABLE
}ETH_DROPTCPIPCHECKSUMERRORFRAME_T;

/**
 * @brief    ETH Receive Store Forward
 */
typedef enum
{
    ETH_RECEIVESTOREFORWARD_DISABLE,
    ETH_RECEIVESTOREFORWARD_ENABLE
}ETH_RECEIVESTOREFORWARD_T;

/**
 * @brief    ETH Flush Received Frame
 */
typedef enum
{
    ETH_FLUSHRECEIVEDFRAME_ENABLE,
    ETH_FLUSHRECEIVEDFRAME_DISABLE
}ETH_FLUSHRECEIVEDFRAME_T;

/**
 * @brief    ETH Transmit Store Forward
 */
typedef enum
{
    ETH_TRANSMITSTOREFORWARD_DISABLE,
    ETH_TRANSMITSTOREFORWARD_ENABLE
}ETH_TRANSMITSTOREFORWARD_T;

/**
 * @brief    ETH Transmit Threshold Control
 */
typedef enum
{
    ETH_TRANSMITTHRESHOLDCONTROL_64BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_128BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_192BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_256BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_40BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_32BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_24BYTES,
    ETH_TRANSMITTHRESHOLDCONTROL_16BYTES
}ETH_TRANSMITTHRESHOLDCONTROL_T;

/**
 * @brief    ETH Forward Error Frames
 */
typedef enum
{
    ETH_FORWARDERRORFRAMES_DISABLE,
    ETH_FORWARDERRORFRAMES_ENABLE
}ETH_FORWARDERRORFRAMES_T;

/**
 * @brief    ETH Forward Undersized Good Frames
 */
typedef enum
{
    ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE,
    ETH_FORWARDUNDERSIZEDGOODFRAMES_ENABLE
}ETH_FORWARDUNDERSIZEDGOODFRAMES_T;

/**
 * @brief    ETH Receive Threshold Control
 */
typedef enum
{
    ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES,
    ETH_RECEIVEDTHRESHOLDCONTROL_32BYTES,
    ETH_RECEIVEDTHRESHOLDCONTROL_96BYTES,
    ETH_RECEIVEDTHRESHOLDCONTROL_128BYTES
}ETH_RECEIVEDTHRESHOLDCONTROL_T;

/**
 * @brief    ETH Second Frame Operate
 */
typedef enum
{
    ETH_SECONDFRAMEOPERARTE_DISABLE,
    ETH_SECONDFRAMEOPERARTE_ENABLE
}ETH_SECONDFRAMEOPERARTE_T;

/**
 * @brief    ETH Address Aligned Beats
 */
typedef enum
{
    ETH_ADDRESSALIGNEDBEATS_DISABLE,
    ETH_ADDRESSALIGNEDBEATS_ENABLE
}ETH_ADDRESSALIGNEDBEATS_T;

/**
 * @brief    ETH Fixed Burst
 */
typedef enum
{
    ETH_FIXEDBURST_DISABLE,
    ETH_FIXEDBURST_ENABLE
}ETH_FIXEDBURST_T;

/**
 * @brief    ETH Rx DMA Burst Length
 */
typedef enum
{
    ETH_RXDMABURSTLENGTH_1BEAT        = BIT17,
    ETH_RXDMABURSTLENGTH_2BEAT        = BIT18,
    ETH_RXDMABURSTLENGTH_4BEAT        = BIT19,
    ETH_RXDMABURSTLENGTH_8BEAT        = BIT20,
    ETH_RXDMABURSTLENGTH_16BEAT       = BIT21,
    ETH_RXDMABURSTLENGTH_32BEAT       = BIT22,
    ETH_RXDMABURSTLENGTH_4XPBL_4BEAT  = BIT17|BIT24,
    ETH_RXDMABURSTLENGTH_4XPBL_8BEAT  = BIT18|BIT24,
    ETH_RXDMABURSTLENGTH_4XPBL_16BEAT = BIT19|BIT24,
    ETH_RXDMABURSTLENGTH_4XPBL_32BEAT = BIT20|BIT24,
    ETH_RXDMABURSTLENGTH_4XPBL_64BEAT = BIT21|BIT24,
    ETH_RXDMABURSTLENGTH_4XPBL_128BEAT= BIT22|BIT24
}ETH_RXDMABURSTLENGTH_T;

/**
 * @brief    ETH Tx DMA Burst Length
 */
typedef enum
{
    ETH_TXDMABURSTLENGTH_1BEAT        = BIT8,
    ETH_TXDMABURSTLENGTH_2BEAT        = BIT9,
    ETH_TXDMABURSTLENGTH_4BEAT        = BIT10,
    ETH_TXDMABURSTLENGTH_8BEAT        = BIT11,
    ETH_TXDMABURSTLENGTH_16BEAT       = BIT12,
    ETH_TXDMABURSTLENGTH_32BEAT       = BIT13,
    ETH_TXDMABURSTLENGTH_4XPBL_4BEAT  = BIT8|BIT24,
    ETH_TXDMABURSTLENGTH_4XPBL_8BEAT  = BIT9|BIT24,
    ETH_TXDMABURSTLENGTH_4XPBL_16BEAT = BIT10|BIT24,
    ETH_TXDMABURSTLENGTH_4XPBL_32BEAT = BIT11|BIT24,
    ETH_TXDMABURSTLENGTH_4XPBL_64BEAT = BIT12|BIT24,
    ETH_TXDMABURSTLENGTH_4XPBL_128BEAT= BIT13|BIT24
}ETH_TXDMABURSTLENGTH_T;

/**
 * @brief    ETH DMA Arbitration
 */
typedef enum
{
    ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1,
    ETH_DMAARBITRATION_ROUNDROBIN_RXTX_2_1 = BIT14,
    ETH_DMAARBITRATION_ROUNDROBIN_RXTX_3_1 = BIT15,
    ETH_DMAARBITRATION_ROUNDROBIN_RXTX_4_1 = BIT14|BIT15,
    ETH_DMAARBITRATION_RXPRIORTX = BIT1
}ETH_DMAARBITRATION_T;

/**
 * @brief    ETH DMA Flags
 */
typedef enum
{
    ETH_DMA_FLAG_TST               = 0x20000000,   //!< Time-stamp trigger interrupt (on DMA)
    ETH_DMA_FLAG_PMT               = 0x10000000,   //!< PMT interrupt (on DMA)
    ETH_DMA_FLAG_MMC               = 0x08000000,   //!< MMC interrupt (on DMA)
    ETH_DMA_FLAG_DATATRANSFERERROR = 0x00800000,   //!< Error bits 0-Rx DMA, 1-Tx DMA
    ETH_DMA_FLAG_READWRITEERROR    = 0x01000000,   //!< Error bits 0-write transfer, 1-read transfer
    ETH_DMA_FLAG_ACCESSERROR       = 0x02000000,   //!< Error bits 0-data buffer, 1-desc. access
    ETH_DMA_FLAG_NIS               = 0x00010000,   //!< Normal interrupt summary flag
    ETH_DMA_FLAG_AIS               = 0x00008000,   //!< Abnormal interrupt summary flag
    ETH_DMA_FLAG_ER                = 0x00004000,   //!< Early receive flag
    ETH_DMA_FLAG_FBE               = 0x00002000,   //!< Fatal bus error flag
    ETH_DMA_FLAG_ET                = 0x00000400,   //!< Early transmit flag
    ETH_DMA_FLAG_RWT               = 0x00000200,   //!< Receive watchdog timeout flag
    ETH_DMA_FLAG_RPS               = 0x00000100,   //!< Receive process stopped flag
    ETH_DMA_FLAG_RBU               = 0x00000080,   //!< Receive buffer unavailable flag
    ETH_DMA_FLAG_RX                = 0x00000040,   //!< Receive flag
    ETH_DMA_FLAG_TU                = 0x00000020,   //!< Underflow flag
    ETH_DMA_FLAG_RO                = 0x00000010,   //!< Overflow flag
    ETH_DMA_FLAG_TJT               = 0x00000008,   //!< Transmit jabber timeout flag
    ETH_DMA_FLAG_TBU               = 0x00000004,   //!< Transmit buffer unavailable flag
    ETH_DMA_FLAG_TPS               = 0x00000002,   //!< Transmit process stopped flag
    ETH_DMA_FLAG_TX                = 0x00000001    //!< Transmit flag
}ETH_DMA_FLAG_T;

/**
 * @brief    ETH DMA Interrupts
 */
typedef enum
{
    ETH_DMA_INT_TST   =   0x20000000,   //!< Time-stamp trigger interrupt (on DMA)
    ETH_DMA_INT_PMT   =   0x10000000,   //!< PMT interrupt (on DMA)
    ETH_DMA_INT_MMC   =   0x08000000,   //!< MMC interrupt (on DMA)
    ETH_DMA_INT_NIS   =   0x00010000,   //!< Normal interrupt summary
    ETH_DMA_INT_AIS   =   0x00008000,   //!< Abnormal interrupt summary
    ETH_DMA_INT_ER    =   0x00004000,   //!< Early receive interrupt
    ETH_DMA_INT_FBE   =   0x00002000,   //!< Fatal bus error interrupt
    ETH_DMA_INT_ET    =   0x00000400,   //!< Early transmit interrupt
    ETH_DMA_INT_RWT   =   0x00000200,   //!< Receive watchdog timeout interrupt
    ETH_DMA_INT_RPS   =   0x00000100,   //!< Receive process stopped interrupt
    ETH_DMA_INT_RBU   =   0x00000080,   //!< Receive buffer unavailable interrupt
    ETH_DMA_INT_RX    =   0x00000040,   //!< Receive interrupt
    ETH_DMA_INT_TU    =   0x00000020,   //!< Underflow interrupt
    ETH_DMA_INT_RO    =   0x00000010,   //!< Overflow interrupt
    ETH_DMA_INT_TJT   =   0x00000008,   //!< Transmit jabber timeout interrupt
    ETH_DMA_INT_TBU   =   0x00000004,   //!< Transmit buffer unavailable interrupt
    ETH_DMA_INT_TPS   =   0x00000002,   //!< Transmit process stopped interrupt
    ETH_DMA_INT_TX    =   0x00000001    //!< Transmit interrupt
}ETH_DMA_INT_T;

/**
 * @brief    ETH DMA transmit process state
 */
typedef enum
{
    ETH_DMA_TRANSMITPROCESS_STOPPED,
    ETH_DMA_TRANSMITPROCESS_FETCHING,
    ETH_DMA_TRANSMITPROCESS_WAITING,
    ETH_DMA_TRANSMITPROCESS_READING,
    ETH_DMA_TRANSMITPROCESS_SUSPENDED = 0x06 ,
    ETH_DMA_TRANSMITPROCESS_CLOSING = 0x07,
}ETH_DMA_TRANSMITPROCESS_T;

/**
 * @brief    ETH DMA receive process state
 */
typedef enum
{
    ETH_DMA_RECEIVEPROCESS_STOPPED,
    ETH_DMA_RECEIVEPROCESS_FETCHING  = 0x02,
    ETH_DMA_RECEIVEPROCESS_WAITING   = 0x06,
    ETH_DMA_RECEIVEPROCESS_SUSPENDED = 0x08,
    ETH_DMA_RECEIVEPROCESS_CLOSING   = 0x0A,
    ETH_DMA_RECEIVEPROCESS_QUEUING   = 0x0E
}ETH_DMA_RECEIVEPROCESS_T;

/**
 * @brief    ETH DMA overflow
 */
typedef enum
{
    ETH_DMA_OVERFLOW_RXFIFOCOUNTER = BIT28,
    ETH_DMA_OVERFLOW_MISSEDFRAMECOUNTER = BIT16
}ETH_DMA_OVERFLOW_T;

/**
 * @brief    ETH PMT Flags
 */
typedef enum
{
    ETH_PMT_FLAG_WUFFRPR = (int)BIT31,
    ETH_PMT_FLAG_WUFR = BIT6,
    ETH_PMT_FLAG_MPR = BIT5
}ETH_PMT_FLAG_T;

/**
 * @brief    ETH MMC Tx/RX Interrupts
 */
typedef enum
{
    ETH_MMC_INT_TGF    = BIT21,
    ETH_MMC_INT_TGFMSC = BIT15,
    ETH_MMC_INT_TGFSC  = BIT14,
    ETH_MMC_INT_RGUF   = BIT21|BIT30,
    ETH_MMC_INT_RFAE   = BIT6|BIT30,
    ETH_MMC_INT_RFCE   = BIT5|BIT30
}ETH_MMC_INT_T;

/**
 * @brief    ETH MMC Registers
 */
typedef enum
{
    ETH_MMC_CTRL       =  0x00000100,
    ETH_MMC_RXINT      =  0x00000104,
    ETH_MMC_TXINT      =  0x00000108,
    ETH_MMC_RXINTMASK  =  0x0000010C,
    ETH_MMC_TXINTMASK  =  0x00000110,
    ETH_MMC_TXGFSCCNT  =  0x0000014C,
    ETH_MMC_TXGFMCCNT  =  0x00000150,
    ETH_MMC_TXGFCNT    =  0x00000168,
    ETH_MMC_RXFCECNT   =  0x00000194,
    ETH_MMC_RXFAECNT   =  0x00000198,
    ETH_MMC_RXGUNCNT   =  0x000001C4
}ETH_MMC_REG_T;

/**@} end of group ETH_Enumerations*/


/** @defgroup ETH_DMA_TX_Descriptor ETH DMA TX Descriptor
  * @{
  */

/**
*  DMA Tx Descriptor
*  -----------------------------------------------------------------------------------------------
*  TXDES0 | OWN(31) | CTRL[30:25] | Reserved(24) | CTRL[23:20] | Reserved[19:18] | Status[17:0]   |
*  -----------------------------------------------------------------------------------------------
*  TXDES1 | Reserved[31:29] | Buffer2 Size[28:16] | Reserved[15:13] | Buffer1 Size[12:0]          |
*  -----------------------------------------------------------------------------------------------
*  TXDES2 |                         Buffer1 Address [31:0]                                        |
*  -----------------------------------------------------------------------------------------------
*  TXDES3 |                   Buffer2 Address [31:0] / Next Descriptor Address [31:0]             |
*  -----------------------------------------------------------------------------------------------
*/

/**
  * @brief  Bit definition of TXDES0 register: DMA Tx descriptor status register
  */
#define ETH_DMATXDESC_OWN                     0x80000000U   //!< OWN bit: descriptor is owned by DMA engine
#define ETH_DMATXDESC_INTC                    0x40000000U   //!< Interrupt on Completion
#define ETH_DMATXDESC_LS                      0x20000000U   //!< Last Segment
#define ETH_DMATXDESC_FS                      0x10000000U   //!< First Segment
#define ETH_DMATXDESC_DISC                    0x08000000U   //!< Disable CRC
#define ETH_DMATXDESC_DISP                    0x04000000U   //!< Disable Padding
#define ETH_DMATXDESC_TXTSEN                  0x02000000U   //!< Transmit Time Stamp Enable
#define ETH_DMATXDESC_CIC                     0x00C00000U   //!< Checksum Insertion Control: 4 cases
#define ETH_DMATXDESC_CIC_BYPASS              0x00000000U   //!< Do Nothing: Checksum Engine is bypassed
#define ETH_DMATXDESC_CIC_IPV4HEADER          0x00400000U   //!< IPV4 header Checksum Insertion
#define ETH_DMATXDESC_CIC_TCPUDPICMP_SEGMENT  0x00800000U   //!< TCP/UDP/ICMP Checksum Insertion calculated over segment only
#define ETH_DMATXDESC_CIC_TCPUDPICMP_FULL     0x00C00000U   //!< TCP/UDP/ICMP Checksum Insertion fully calculated
#define ETH_DMATXDESC_TXENDR                  0x00200000U   //!< Transmit End of Ring
#define ETH_DMATXDESC_TXCH                    0x00100000U   //!< Second Address Chained
#define ETH_DMATXDESC_TXTSS                   0x00020000U   //!< Tx Time Stamp Status
#define ETH_DMATXDESC_IHERR                   0x00010000U   //!< IP Header Error
#define ETH_DMATXDESC_ERRS                    0x00008000U   //!< Error summary: OR of the following bits: UFERR || EDEF || EC || LC || NC || LSC || FF || JTO
#define ETH_DMATXDESC_JTO                     0x00004000U   //!< Jabber Timeout
#define ETH_DMATXDESC_FF                      0x00002000U   //!< Frame Flushed: DMA/MTL flushed the frame due to SW flush
#define ETH_DMATXDESC_IPERR                   0x00001000U   //!< Payload Checksum Error
#define ETH_DMATXDESC_LSC                     0x00000800U   //!< Loss of Carrier: carrier lost during transmission
#define ETH_DMATXDESC_NC                      0x00000400U   //!< No Carrier: no carrier signal from the transceiver
#define ETH_DMATXDESC_LC                      0x00000200U   //!< Late Collision: transmission aborted due to collision
#define ETH_DMATXDESC_EC                      0x00000100U   //!< Excessive Collision: transmission aborted after 16 collisions
#define ETH_DMATXDESC_VLANF                   0x00000080U   //!< VLAN Frame
#define ETH_DMATXDESC_CCNT                    0x00000078U   //!< Collision Count
#define ETH_DMATXDESC_EDEF                    0x00000004U   //!< Excessive Deferral
#define ETH_DMATXDESC_UFERR                   0x00000002U   //!< Underflow Error: late data arrival from the memory
#define ETH_DMATXDESC_DEF                     0x00000001U   //!< Deferred Bit

/**
  * @brief  Bit definition of TXDES1 register
  */
#define ETH_DMATXDESC_TXBS2  0x1FFF0000U //!< Transmit Buffer2 Size
#define ETH_DMATXDESC_TXBS1  0x00001FFFU //!< Transmit Buffer1 Size

/**
  * @brief  Bit definition of TXDES2 register
  */
#define ETH_DMATXDESC_B1AP  0xFFFFFFFFU //!< Buffer1 Address Pointer

/**
  * @brief  Bit definition of TXDES3 register
  */
#define ETH_DMATXDESC_B2AP  0xFFFFFFFFU //!< Buffer2 Address Pointer

/**
*  ---------------------------------------------------------------------------------------------
*  TXDES6 |                         Transmit Time Stamp Low [31:0]                               |
*  ---------------------------------------------------------------------------------------------
*  TXDES7 |                         Transmit Time Stamp High [31:0]                              |
*  ----------------------------------------------------------------------------------------------
*/

/** Bit definition of TXDES6 register */
#define ETH_DMAPTPTXDESC_TXTSL  0xFFFFFFFFU  //!< Transmit Time Stamp Low

/** Bit definition of TXDES7 register */
#define ETH_DMAPTPTXDESC_TXTSH  0xFFFFFFFFU  //!< Transmit Time Stamp High

/**
  * @}
  */
/** @defgroup ETH_DMA_RX_Descriptor ETH DMA RX Descriptor
  * @{
  */

/**
  *DMA Rx Descriptor
  *--------------------------------------------------------------------------------------------------------------------
  *RXDES0 | OWN(31) |                                             Status [30:0]                                         |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES1 | CTRL(31) | Reserved[30:29] | Buffer2 Size[28:16] | CTRL[15:14] | Reserved(13) | Buffer1 Size[12:0]          |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES2 |                                       Buffer1 Address [31:0]                                                |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES3 |                          Buffer2 Address [31:0] / Next Descriptor Address [31:0]                            |
  *---------------------------------------------------------------------------------------------------------------------
*/

/**
  * @brief  Bit definition of RXDES0 register: DMA Rx descriptor status register
  */
#define ETH_DMARXDESC_OWN         0x80000000U   //!< OWN bit: descriptor is owned by DMA engine
#define ETH_DMARXDESC_ADDRF       0x40000000U   //!< DA Filter Fail for the rx frame
#define ETH_DMARXDESC_FL          0x3FFF0000U   //!< Receive descriptor frame length
#define ETH_DMARXDESC_ERRS        0x00008000U   //!< Error summary: OR of the following bits: DE || OE || IPC || LC || RWT || RE || CE
#define ETH_DMARXDESC_DESERR      0x00004000U   //!< Descriptor error: no more descriptors for receive frame
#define ETH_DMARXDESC_SADDRF      0x00002000U   //!< SA Filter Fail for the received frame
#define ETH_DMARXDESC_LERR        0x00001000U   //!< Frame size not matching with length field
#define ETH_DMARXDESC_OFERR       0x00000800U   //!< Overflow Error: Frame was damaged due to buffer overflow
#define ETH_DMARXDESC_VLANF       0x00000400U   //!< VLAN Tag: received frame is a VLAN frame
#define ETH_DMARXDESC_FDES        0x00000200U   //!< First descriptor of the frame
#define ETH_DMARXDESC_LDES        0x00000100U   //!< Last descriptor of the frame
#define ETH_DMARXDESC_IPV4HCE     0x00000080U   //!< IPC Checksum Error: Rx Ipv4 header checksum error
#define ETH_DMARXDESC_LC          0x00000040U   //!< Late collision occurred during reception
#define ETH_DMARXDESC_FT          0x00000020U   //!< Frame type - Ethernet, otherwise 802.3
#define ETH_DMARXDESC_RXWWTTO     0x00000010U   //!< Receive Watchdog Timeout: watchdog timer expired during reception
#define ETH_DMARXDESC_RERR        0x00000008U   //!< Receive error: error reported by MII interface
#define ETH_DMARXDESC_DERR        0x00000004U   //!< Dribble bit error: frame contains non int multiple of 8 bits
#define ETH_DMARXDESC_CERR        0x00000002U   //!< CRC error
#define ETH_DMARXDESC_MAMPCE      0x00000001U   //!< Rx MAC Address/Payload Checksum Error: Rx MAC address matched/ Rx Payload Checksum Error

/**
  * @brief  Bit definition of RXDES1 register
  */
#define ETH_DMARXDESC_DINTC  0x80000000U //!< Disable Interrupt on Completion
#define ETH_DMARXDESC_RXBS2  0x1FFF0000U //!< Receive Buffer2 Size
#define ETH_DMARXDESC_RXER   0x00008000U //!< Receive End of Ring
#define ETH_DMARXDESC_RXCH   0x00004000U //!< Second Address Chained
#define ETH_DMARXDESC_RXBS1  0x00001FFFU //!< Receive Buffer1 Size

/**
  * @brief  Bit definition of RXDES2 register
  */
#define ETH_DMARXDESC_B1AP  0xFFFFFFFFU //!< Buffer1 Address Pointer

/**
  * @brief  Bit definition of RXDES3 register
  */
#define ETH_DMARXDESC_B2AP  0xFFFFFFFFU //!< Buffer2 Address Pointer

/**
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES4 |                   Reserved[31:14]              |             Extended Status [13:0]                         |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES5 |                                            Reserved[31:0]                                                   |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES6 |                                       Receive Time Stamp Low [31:0]                                         |
  *---------------------------------------------------------------------------------------------------------------------
  *RXDES7 |                                       Receive Time Stamp High [31:0]                                        |
  *---------------------------------------------------------------------------------------------------------------------
*/

/** Bit definition of RXDES4 register */
#define ETH_DMAPTPRXDESC_PTPV     0x00002000U   //!< PTP Version
#define ETH_DMAPTPRXDESC_PTPFT    0x00001000U   //!< PTP Frame Type
#define ETH_DMAPTPRXDESC_PTPMT    0x00000F00U   //!< PTP Message Type
#define ETH_DMAPTPRXDESC_PTPMT_SYNC                      0x00000100U    //!< SYNC message (all clock types)
#define ETH_DMAPTPRXDESC_PTPMT_FOLLOWUP                  0x00000200U    //!< FollowUp message (all clock types)
#define ETH_DMAPTPRXDESC_PTPMT_DELAYREQ                  0x00000300U    //!< DelayReq message (all clock types)
#define ETH_DMAPTPRXDESC_PTPMT_DELAYRESP                 0x00000400U    //!< DelayResp message (all clock types)
#define ETH_DMAPTPRXDESC_PTPMT_PDELAYREQ_ANNOUNCE        0x00000500U    //!< PdelayReq message (peer-to-peer transparent clock) or Announce message (Ordinary or Boundary clock)
#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESP_MANAG          0x00000600U    //!< PdelayResp message (peer-to-peer transparent clock) or Management message (Ordinary or Boundary clock)
#define ETH_DMAPTPRXDESC_PTPMT_PDELAYRESPFOLLOWUP_SIGNAL 0x00000700U    //!< PdelayRespFollowUp message (peer-to-peer transparent clock) or Signaling message (Ordinary or Boundary clock)
#define ETH_DMAPTPRXDESC_IPV6P    0x00000080U   //!< IPv6 Packet Received
#define ETH_DMAPTPRXDESC_IPV4P    0x00000040U   //!< IPv4 Packet Received
#define ETH_DMAPTPRXDESC_IPCBP    0x00000020U   //!< IP Checksum Bypassed
#define ETH_DMAPTPRXDESC_IPPERR   0x00000010U   //!< IP Payload Error
#define ETH_DMAPTPRXDESC_IPHERR   0x00000008U   //!< IP Header Error
#define ETH_DMAPTPRXDESC_IPPT     0x00000007U   //!< IP Payload Type
#define ETH_DMAPTPRXDESC_IPPT_UDP                 0x00000001U   //!< UDP payload encapsulated in the IP datagram
#define ETH_DMAPTPRXDESC_IPPT_TCP                 0x00000002U   //!< TCP payload encapsulated in the IP datagram
#define ETH_DMAPTPRXDESC_IPPT_ICMP                0x00000003U   //!< ICMP payload encapsulated in the IP datagram

/** Bit definition of RXDES6 register */
#define ETH_DMAPTPRXDESC_RXTSL  0xFFFFFFFFU  //!< Receive Time Stamp Low

/** Bit definition of RXDES7 register */
#define ETH_DMAPTPRXDESC_RXTSH  0xFFFFFFFFU  //!< Receive Time Stamp High
/**
  * @}
  */


/** @addtogroup ETH_Macros Macros
  *@{
  */

/** ETH Frames defines */

/** Definition of the Ethernet driver buffers size and count */
#define ETH_RX_BUF_SIZE                ETH_MAX_PACKET_SIZE  //!< buffer size for receive
#define ETH_TX_BUF_SIZE                ETH_MAX_PACKET_SIZE  //!< buffer size for transmit
#define ETH_RXBUFNB                    (10U)    //!< 10 Rx buffers of size ETH_RX_BUF_SIZE
#define ETH_TXBUFNB                    (10U)    //!< 10 Tx buffers of size ETH_TX_BUF_SIZE

/** ETH_Buffers_setting ETH Buffers setting */
#define ETH_MAX_PACKET_SIZE       1524U //!< ETH_HEADER + ETH_EXTRA + ETH_VLAN_TAG + ETH_MAX_ETH_PAYLOAD + ETH_CRC
#define ETH_HEADER                14U   //!< 6 byte Dest addr, 6 byte Src addr, 2 byte length/type
#define ETH_CRC                   4U    //!< Ethernet CRC
#define ETH_EXTRA                 2U    //!< Extra bytes in some cases
#define ETH_VLAN_TAG              4U    //!< optional 802.1q VLAN Tag
#define ETH_MIN_ETH_PAYLOAD       46U   //!< Minimum Ethernet payload size
#define ETH_MAX_ETH_PAYLOAD       1500U //!< Maximum Ethernet payload size
#define ETH_JUMBO_FRAME_PAYLOAD   9000U //!< Jumbo frame payload size

/**
*  Ethernet driver receive buffers are organized in a chained linked-list, when
*  an ethernet packet is received, the Rx-DMA will transfer the packet from RxFIFO
*  to the driver receive buffers memory.
*
*  Depending on the size of the received ethernet packet and the size of
*  each ethernet driver receive buffer, the received packet can take one or more
*  ethernet driver receive buffer.
*
*  In below are defined the size of one ethernet driver receive buffer ETH_RX_BUF_SIZE
*  and the total count of the driver receive buffers ETH_RXBUFNB.
*
*  The configured value for ETH_RX_BUF_SIZE and ETH_RXBUFNB are only provided as
*  example, they can be reconfigured in the application layer to fit the application
*  needs
*/

/** Here we configure each Ethernet driver receive buffer to fit the Max size Ethernet
*   packet
*/
#ifndef ETH_RX_BUF_SIZE
#define ETH_RX_BUF_SIZE         ETH_MAX_PACKET_SIZE
#endif

/** 5 Ethernet driver receive buffers are used (in a chained linked list)*/
#ifndef ETH_RXBUFNB
#define ETH_RXBUFNB             5U  //!< 5 Rx buffers of size ETH_RX_BUF_SIZE
#endif

/**
*  Ethernet driver transmit buffers are organized in a chained linked-list, when
*  an ethernet packet is transmitted, Tx-DMA will transfer the packet from the
*  driver transmit buffers memory to the TxFIFO.
*
*  Depending on the size of the Ethernet packet to be transmitted and the size of
*  each ethernet driver transmit buffer, the packet to be transmitted can take
*  one or more ethernet driver transmit buffer.
*
*  In below are defined the size of one ethernet driver transmit buffer ETH_TX_BUF_SIZE
*  and the total count of the driver transmit buffers ETH_TXBUFNB.
*
*  The configured value for ETH_TX_BUF_SIZE and ETH_TXBUFNB are only provided as
*  example, they can be reconfigured in the application layer to fit the application
*  needs
*/

/** Here we configure each Ethernet driver transmit buffer to fit the Max size Ethernet
*   packet
*/
#ifndef ETH_TX_BUF_SIZE
#define ETH_TX_BUF_SIZE         ETH_MAX_PACKET_SIZE
#endif

/** 5 ethernet driver transmit buffers are used (in a chained linked list)*/
#ifndef ETH_TXBUFNB
#define ETH_TXBUFNB             5U  //!< 5  Tx buffers of size ETH_TX_BUF_SIZE
#endif

/** ETHERNET MAC address offsets */
#define ETH_MAC_ADDR_HBASE   (ETH_MAC_BASE + 0x40)  //!< ETHERNET MAC address high offset
#define ETH_MAC_ADDR_LBASE    (ETH_MAC_BASE + 0x44)  //!< ETHERNET MAC address low offset

/** ETHERNET Errors */
#define  ETH_SUCCESS            1U
#define  ETH_ERROR              0U

/** ETHERNET DMA Tx descriptors Collision Count Shift */
#define  ETH_DMATXDESC_COLLISION_COUNTSHIFT        3U

/** ETHERNET DMA Tx descriptors Buffer2 Size Shift */
#define  ETH_DMATXDESC_BUFFER2_SIZESHIFT           16U

/** ETHERNET DMA Rx descriptors Frame Length Shift */
#define  ETH_DMARXDESC_FRAME_LENGTHSHIFT           16U

/** ETHERNET DMA Rx descriptors Buffer2 Size Shift */
#define  ETH_DMARXDESC_BUFFER2_SIZESHIFT           16U

/** ETHERNET DMA Rx descriptors Frame length Shift */
#define  ETH_DMARXDESC_FRAMELENGTHSHIFT            16U

/** ETHERNET MACMIIAR register Mask */
#define ETH_MACMIIAR_CR_MASK    0xFFFFFFE3U

/** ETHERNET MACCR register Mask */
#define ETH_MACCR_CLEAR_MASK    0xFF20010FU

/** ETHERNET MACFCR register Mask */
#define ETH_MACFCR_CLEAR_MASK   0x0000FF41U

/** ETHERNET DMAOMR register Mask */
#define ETH_DMAOMR_CLEAR_MASK   0xF8DE3F23U

/** ETHERNET Remote Wake-up frame register length */
#define ETH_WAKEUP_REGISTER_LENGTH      8U

/** ETHERNET Missed frames counter Shift */
#define  ETH_DMA_RX_OVERFLOW_MISSEDFRAMES_COUNTERSHIFT     17U

/** PHY registers defines */

/** PHY Read write Timeouts */
#define PHY_READ_TIMEOUT                ((uint32_t)0x0004FFFF)
#define PHY_WRITE_TIMEOUT               ((uint32_t)0x0004FFFF)

/** PHY Register address */
#define PHY_BCR                                      0         //!< Transceiver Basic Control Register
#define PHY_BSR                                      1         //!< Transceiver Basic Status Register

#if defined (APM32F407_EVAL)
#define PHY_SR                                       31        //!< Transceiver Status Register for LAN8720
#else
#define PHY_SR                                       16        //!< Transceiver Status Register for dp83848
#endif

/** PHY Status Register (PHYSTS), address 0x10 */
#if defined (APM32F407_EVAL)
#define PHY_DUPLEX_STATUS               ((uint16_t)0x0010)     //!< for LAN8720 
#define PHY_SPEED_STATUS                ((uint16_t)0x0004)     //!< for LAN8720 
#else
#define PHY_DUPLEX_STATUS               ((uint16_t)0x0004)     //!< for dp83848 
#define PHY_SPEED_STATUS                ((uint16_t)0x0002)     //!< for dp83848 
#endif

/** PHY basic status register */
#define PHY_AUTONEGO_COMPLETE           ((uint16_t)0x0020)     //!< Auto-Negotiation process completed
#define PHY_LINKED_STATUS               ((uint16_t)0x0004)     //!< Valid link established
#define PHY_JABBER_DETECTION            ((uint16_t)0x0002)     //!< Jabber condition detected

/** PHY basic Control register */
#define PHY_RESET                       ((uint16_t)0x8000)     //!< PHY Reset
#define PHY_LOOPBACK                    ((uint16_t)0x4000)     //!< Select loop-back mode
#define PHY_FULLDUPLEX_100M             ((uint16_t)0x2100)     //!< Set the full-duplex mode at 100 Mb/s
#define PHY_HALFDUPLEX_100M             ((uint16_t)0x2000)     //!< Set the half-duplex mode at 100 Mb/s
#define PHY_FULLDUPLEX_10M              ((uint16_t)0x0100)     //!< Set the full-duplex mode at 10 Mb/s
#define PHY_HALFDUPLEX_10M              ((uint16_t)0x0000)     //!< Set the half-duplex mode at 10 Mb/s
#define PHY_AUTONEGOTIATION             ((uint16_t)0x1000)     //!< Enable auto-negotiation function
#define PHY_RESTAET_AUTONEGOTIATION     ((uint16_t)0x0200)     //!< Restart auto-negotiation function
#define PHY_POWERDOWN                   ((uint16_t)0x0800)     //!< Select the power down mode
#define PHY_ISOLATE                     ((uint16_t)0x0400)     //!< Isolate PHY from MII

/** PHY Delay */
#define PHY_RESET_DELAY                 ((uint32_t)0x000FFFFF) //!< PHY reset delay
#define PHY_CONFIG_DELAY                ((uint32_t)0x00FFFFFF) //!< PHY configuration delay
/** Delay to wait when writing to some Ethernet registers */
#define ETH_REG_WRITE_DELAY             ((uint32_t)0x0000FFFF)

/** Ethernet MAC MII Address Clock Range*/
#define ETH_MACMIIAR_CR_DIV42   ((uint8_t)0x00)  //!< HCLK:60-100 MHz; MDC clock= HCLK/42
#define ETH_MACMIIAR_CR_DIV62   ((uint8_t)0x01)  //!< HCLK:100-150 MHz; MDC clock= HCLK/62
#define ETH_MACMIIAR_CR_DIV16   ((uint8_t)0x02)  //!< HCLK:20-35 MHz; MDC clock= HCLK/16
#define ETH_MACMIIAR_CR_DIV26   ((uint8_t)0x03)  //!< HCLK:35-60 MHz; MDC clock= HCLK/26
#define ETH_MACMIIAR_CR_DIV102  ((uint8_t)0x04)  //!< HCLK:150-168 MHz; MDC clock= HCLK/102

/** Control the Enhanced DMA descriptors */
#define USE_ENHANCED_DMA_DESCRIPTORS     1

/**@} end of group ETH_Macros */


/** @addtogroup ETH_Structure Data Structure
  @{
*/

/**
 * @brief    ETH MAC Config structure types
 */
typedef struct
{
    /** MAC Configuration */
    ETH_AUTONEGOTIATION_T           autoNegotiation;           /** Selects or not the AutoNegotiation mode for the external PHY
                                                                 * The AutoNegotiation allows an automatic setting of the Speed (10/100Mbps)
                                                                 * and the mode (half/full-duplex)
                                                                 */

    ETH_WATCHDOG_T                  watchDog;                  /** Selects or not the Watchdog timer
                                                                 * When enabled, the MAC allows no more then 2048 bytes to be received.
                                                                 * When disabled, the MAC can receive up to 16384 bytes.
                                                                 */

    ETH_JABBER_T                    jabber;                    /** Selects or not Jabber timer
                                                                 * When enabled, the MAC allows no more then 2048 bytes to be sent.
                                                                 * When disabled, the MAC can send up to 16384 bytes.
                                                                 */
    ETH_INTERFRAMEGAP_T             interFrameGap;             /** Selects the minimum IFG between frames during transmission */

    ETH_CARRIERSENCE_T              carrierSense;              //!< Selects or not the Carrier Sense

    ETH_SPEED_T                     speed;                     //!< Sets the Ethernet speed: 10/100 Mbps

    ETH_RECEIVEOWN_T                receiveOwn;                /** Selects or not the ReceiveOwn
                                                                 * ReceiveOwn allows the reception of frames when the TX_EN signal is asserted
                                                                 * in Half-Duplex mode
                                                                 */

    ETH_LOOPBACKMODE_T              loopbackMode;              //!< Selects or not the internal MAC MII Loopback mode

    ETH_MODE_T                      mode;                      //!< Selects the MAC duplex mode: Half-Duplex or Full-Duplex mode

    ETH_CHECKSUMOFFLAOD_T           checksumOffload;           //!< Selects or not the IPv4 checksum checking for received frame payloads' TCP/UDP/ICMP headers.

    ETH_RETRYTRANSMISSION_T         retryTransmission;         /** Selects or not the MAC attempt retries transmission, based on the settings of BL,
                                                                 * when a collision occurs (Half-Duplex mode)
                                                                 */

    ETH_AUTOMATICPADCRCSTRIP_T      automaticPadCRCStrip;      //!< Selects or not the Automatic MAC Pad/CRC Stripping

    ETH_BACKOFFLIMIT_T              backOffLimit;              //!< Selects the BackOff limit value

    ETH_DEFFERRALCHECK_T            deferralCheck;             //!< Selects or not the deferral check function (Half-Duplex mode)

    ETH_RECEIVEAll_T                receiveAll;                //!< Selects or not all frames reception by the MAC (No filtering)

    ETH_SOURCEADDRFILTER_T          sourceAddrFilter;          //!< Selects the Source Address Filter mode

    ETH_PASSCONTROLFRAMES_T         passControlFrames;         //!< Sets the forwarding mode of the control frames (including unicast and multicast PAUSE frames)

    ETH_BROADCASTFRAMESRECEPTION_T  broadcastFramesReception;  //!< Selects or not the reception of Broadcast Frames

    ETH_DESTINATIONADDRFILTER_T     destinationAddrFilter;     //!< Sets the destination filter mode for both unicast and multicast frames

    ETH_PROMISCUOUS_MODE_T          promiscuousMode;           //!< Selects or not the Promiscuous Mode

    ETH_MULTICASTFRAMESFILTER_T     multicastFramesFilter;     //!< Selects the Multicast Frames filter mode

    ETH_UNICASTFRAMESFILTER_T       unicastFramesFilter;       //!< Selects the Unicast Frames filter mode


    uint32_t                        hashTableHigh;             //!< This field holds the higher 32 bits of Hash table.

    uint32_t                        hashTableLow;              //!< This field holds the lower 32 bits of Hash table.

    uint32_t                        pauseTime;                 //!< This field holds the (value<=0xFFFF) to be used in the Pause Time

    ETH_ZEROQUANTAPAUSE_T           zeroQuantaPause;           //!< Selects or not the automatic generation of Zero-Quanta Pause Control frames

    ETH_PAUSELOWTHRESHOLD_T         pauseLowThreshold;         /** This field configures the threshold of the PAUSE to be checked for
                                                                 * automatic retransmission of PAUSE Frame
                                                                 */

    ETH_UNICASTPAUSEFRAMEDETECT_T   unicastPauseFrameDetect;   /** Selects or not the MAC detection of the Pause frames (with MAC Address0
                                                                 * unicast address and unique multicast address)
                                                                 */

    ETH_RECEIVEFLOWCONTROL_T        receiveFlowControl;        /** Enables or disables the MAC to decode the received Pause frame and
                                                                 * disable its transmitter for a specified time (Pause Time)
                                                                 */

    ETH_TRANSMITFLOWCONTROL_T       transmitFlowControl;       /** Enables or disables the MAC to transmit Pause frames (Full-Duplex mode)
                                                                 * or the MAC back-pressure operation (Half-Duplex mode)
                                                                 */

    ETH_VLANTAGCOMPARISON_T         VLANTagComparison;         /** Selects the 12-bit VLAN identifier or the complete 16-bit VLAN tag for
                                                                 * comparison and filtering
                                                                 */

    uint32_t                        VLANTagIdentifier;         //!< Holds the (value <=0xFFFF) VLAN tag identifier for receive frames

    /** DMA Configuration */
    ETH_DROPTCPIPCHECKSUMERRORFRAME_T   dropTCPIPChecksumErrorFrame; //!< Selects or not the Dropping of TCP/IP Checksum Error Frames

    ETH_RECEIVESTOREFORWARD_T           receiveStoreForward;         //!< Enables or disables the Receive store and forward mode

    ETH_FLUSHRECEIVEDFRAME_T            flushReceivedFrame;          //!< Enables or disables the flushing of received frames

    ETH_TRANSMITSTOREFORWARD_T          transmitStoreForward;        //!< Enables or disables Transmit store and forward mode

    ETH_TRANSMITTHRESHOLDCONTROL_T      transmitThresholdControl;    //!< Selects or not the Transmit Threshold Control

    ETH_FORWARDERRORFRAMES_T            forwardErrorFrames;          //!< Selects or not the forward to the DMA of erroneous frames

    ETH_FORWARDUNDERSIZEDGOODFRAMES_T   forwardUndersizedGoodFrames; /** Enables or disables the Rx FIFO to forward Undersized frames (frames with no Error
                                                                       * and length less than 64 bytes) including pad-bytes and CRC)
                                                                       */

    ETH_RECEIVEDTHRESHOLDCONTROL_T      receiveThresholdControl;     //!< Selects the threshold level of the Receive FIFO

    ETH_SECONDFRAMEOPERARTE_T           secondFrameOperate;          /** Selects or not the Operate on second frame mode, which allows the DMA to process a second
                                                                       * frame of Transmit data even before obtaining the status for the first frame.
                                                                       */

    ETH_ADDRESSALIGNEDBEATS_T           addressAlignedBeats;         //!< Enables or disables the Address Aligned Beats

    ETH_FIXEDBURST_T                    fixedBurst;                  //!< Enables or disables the AHB Master interface fixed burst transfers

    ETH_RXDMABURSTLENGTH_T              rxDMABurstLength;            //!< Indicates the maximum number of beats to be transferred in one Rx DMA transaction

    ETH_TXDMABURSTLENGTH_T              txDMABurstLength;            //!< Indicates the maximum number of beats to be transferred in one Tx DMA transaction

    uint32_t                            descriptorSkipLength;        //!< Specifies the number of word to skip between two unchained descriptors (Ring mode) (value <= 0x1F)

    ETH_DMAARBITRATION_T                DMAArbitration;              //!< Selects the DMA Tx/Rx arbitration
}ETH_Config_T;

/**
  * @brief  ETH DMA Descriptors data structure types
  */
typedef struct
{
    __IO uint32_t   Status;                            //!< Status
    uint32_t        ControlBufferSize;                 //!< Control and Buffer1, Buffer2 lengths
    uint32_t        Buffer1Addr;                       //!< Buffer1 address pointer
    uint32_t        Buffer2NextDescAddr;               //!< Buffer2 or next descriptor address pointer
    /** Enhanced ETHERNET DMA PTP Descriptors */
    #if USE_ENHANCED_DMA_DESCRIPTORS
    uint32_t        ExtendedStatus;                    //!< Extended status for PTP receive descriptor
    uint32_t        Reserved1;                         //!< Reserved
    uint32_t        TimeStampLow;                      //!< Time Stamp Low value for transmit and receive
    uint32_t        TimeStampHigh;                     //!< Time Stamp High value for transmit and receive
    #endif /** USE_ENHANCED_DMA_DESCRIPTORS */
}ETH_DMADescConfig_T;

/**
  * @brief  ETH DMA Descriptors data structure types
  */
typedef struct
{
    uint32_t        length;
    uint32_t        buffer;
    __IO ETH_DMADescConfig_T *descriptor;
}ETH_Frame_T;

/**
  * @brief  ETH DMA Descriptors Received Frame Informations structure types
  */
typedef struct  {
  __IO ETH_DMADescConfig_T   *FS_RxDesc;              //!< First Segment Rx Desc
  __IO ETH_DMADescConfig_T   *LS_RxDesc;              //!< Last Segment Rx Desc
  __IO uint32_t               segCount;               //!< Segment count
} ETH_DMARxFrameInformations;

/**@} end of group ETH_Structure*/


/** @addtogroup ETH_Fuctions Fuctions
  @{
*/

/** ETH Configuration */
void ETH_Reset(void);
void ETH_ConfigStructInit(ETH_Config_T* ethConfig);
uint32_t ETH_Config(ETH_Config_T* ethConfig, uint16_t addr);
void ETH_SoftwareReset(void);
uint8_t ETH_ReadSoftwareReset(void);
void ETH_Start(void);
void ETH_Stop(void);
uint32_t ETH_ReadRxPacketSize(ETH_DMADescConfig_T *DMARxDesc);
#if USE_ENHANCED_DMA_DESCRIPTORS
void ETH_EnableEnhancedDescriptor(void);
void ETH_DisableEnhancedDescriptor(void);
#endif /** USE_ENHANCED_DMA_DESCRIPTORS */

/** PHY */
uint16_t ETH_ReadPHYRegister(uint16_t addr, uint16_t reg);
uint32_t ETH_WritePHYRegister(uint16_t addr, uint16_t reg, uint16_t data);
uint32_t ETH_EnablePHYLoopBack(uint16_t addr);
uint32_t ETH_DisablePHYLoopBack(uint16_t addr);

/** MAC */
void ETH_EnableMACTransmission(void);
void ETH_DisableMACTransmission(void);
void ETH_EnableMACReceiver(void);
void ETH_DisableMACReceiver(void);
uint8_t ETH_ReadFlowControlBusyStatus(void);
void ETH_SetPauseControlFrame(void);
void ETH_EnableBackPressureActivation(void);
void ETH_DisableBackPressureActivation(void);
uint8_t ETH_ReadMACFlagStatus(ETH_MAC_FLAG_T flag);
void ETH_EnableMACInterrupt(uint32_t interrupt);
void ETH_DisableMACInterrupt(uint32_t interrupt);
void ETH_ConfigMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr);
void ETH_ReadMACAddress(ETH_MAC_ADDRESS_T macAddr, uint8_t *addr);
void ETH_EnableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr);
void ETH_DisableMACAddressPerfectFilter(ETH_MAC_ADDRESS_T macAddr);
void ETH_ConfigMACAddressFilter(ETH_MAC_ADDRESS_T macAddr, ETH_MAC_ADDRESSFILTER_T filter);
void ETH_ConfigMACAddressMaskBytesFilter(ETH_MAC_ADDRESS_T macAddr, uint32_t maskByte);

/** DMA descriptors */
void ETH_ConfigDMARxDescChain(ETH_DMADescConfig_T *DMARxDescTab, uint8_t *rxBuff, uint32_t rxBuffcount);
void ETH_ConfigDMATxDescChain(ETH_DMADescConfig_T *DMATxDescTab, uint8_t* txBuff, uint32_t txBuffcount);
uint32_t ETH_CheckReceivedFrame(void);
uint32_t ETH_Transmit_Descriptors(u16 frameLength);
ETH_Frame_T ETH_ReadReceivedFrame(void);
uint8_t ETH_ReadDMATxDescFlagStatus(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_FLAG_T flag);
uint32_t ETH_ReadDMATxDescCollisionCount(ETH_DMADescConfig_T *DMATxDesc);
void ETH_ConfigDMATxDescOwnBit(ETH_DMADescConfig_T *DMATxDesc);
void ETH_EnableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc);
void ETH_DisableDMATxDescTransmitInterrupt(ETH_DMADescConfig_T *DMATxDesc);
void ETH_ConfigDMATxDescFrameSegment(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_SEGMENTS_T frameSegment);
void ETH_ConfigDMATxDescChecksumInsertion(ETH_DMADescConfig_T *DMATxDesc, ETH_DMATXDESC_CHECKSUMB_T checksum);
void ETH_EnableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc);
void ETH_DisableDMATxDescCRC(ETH_DMADescConfig_T *DMATxDesc);
void ETH_EnableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc);
void ETH_DisableDMATxDescSecondAddressChained(ETH_DMADescConfig_T *DMATxDesc);
void ETH_EnableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc);
void ETH_DisableDMATxDescShortFramePadding(ETH_DMADescConfig_T *DMATxDesc);
void ETH_ConfigDMATxDescBufferSize(ETH_DMADescConfig_T *DMATxDesc, uint32_t bufferSize1, uint32_t bufferSize2);
uint8_t ETH_ReadDMARxDescFlagStatus(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_FLAG_T flag);
#if USE_ENHANCED_DMA_DESCRIPTORS
uint8_t ETH_ReadDMAPTPRxDescExtendedFlagStatus(ETH_DMADescConfig_T *DMAPTPRxDesc, ETH_DMAPTPRXDESC_FLAG_T flag);
#endif
void ETH_ConfigDMARxDescOwnBit(ETH_DMADescConfig_T *DMARxDesc);
uint32_t ETH_ReadDMARxDescFrameLength(ETH_DMADescConfig_T *DMARxDesc);
void ETH_EnableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMARxDesc);
void ETH_DisableDMARxDescReceiveInterrupt(ETH_DMADescConfig_T *DMATxDesc);
uint32_t ETH_ReadDMARxDescBufferSize(ETH_DMADescConfig_T *DMARxDesc, ETH_DMARXDESC_BUFFER_T buffer);
ETH_Frame_T ETH_ReadReceivedFrameInterrupt(void);

/** DMA */
uint8_t ETH_ReadDMAFlagStatus(ETH_DMA_FLAG_T flag);
void ETH_ClearDMAFlag(uint32_t flag);
uint8_t ETH_ReadDMAIntFlag(ETH_DMA_INT_T flag);
void ETH_ClearDMAIntFlag(uint32_t flag);
uint32_t ETH_ReadTransmitProcessState(void);
uint32_t ETH_ReadReceiveProcessState(void);
void ETH_FlushTransmitFIFO(void);
uint8_t ETH_ReadFlushTransmitFIFOStatus(void);
void ETH_EnableDMATransmission(void);
void ETH_DisableDMATransmission(void);
void ETH_EnableDMAReceiver(void);
void ETH_DisableDMAReceiver(void);
void ETH_EnableDMAInterrupt(uint32_t interrupt);
void ETH_DisableDMAInterrupt(uint32_t interrupt);
uint8_t ETH_ReadDMAOverflowStatus(ETH_DMA_OVERFLOW_T overflow);
uint32_t ETH_ReadRxOverflowMissedFrameCounter(void);
uint32_t ETH_ReadBufferUnavailableMissedFrameCounter(void);
uint32_t ETH_ReadCurrentTxDescStartAddress(void);
uint32_t ETH_ReadCurrentRxDescStartAddress(void);
uint32_t ETH_ReadCurrentTxBufferAddress(void);
uint32_t ETH_ReadCurrentRxBufferAddress(void);
void ETH_ResetDMATransmission(void);
void ETH_ResetDMAReception(void);
void ETH_ConfigReceiveWatchdogTimer(uint8_t value);

/** PMT */
void ETH_ResetWakeUpFrameFilterRegisterPointer(void);
void ETH_ConfigWakeUpFrameFilterRegister(uint32_t *buffer);
void ETH_EnableGlobalUnicastWakeUp(void);
void ETH_DisableGlobalUnicastWakeUp(void);
uint8_t ETH_ReadPMTFlagStatus(ETH_PMT_FLAG_T flag);
void ETH_EnableWakeUpFrameDetection(void);
void ETH_DisableWakeUpFrameDetection(void);
void ETH_EnableMagicPacketDetection(void);
void ETH_DisableMagicPacketDetection(void);
void ETH_EnablePowerDown(void);
void ETH_DisablePowerDown(void);

/** MMC */
void ETH_PresetMMCCounterFull(void);
void ETH_PresetMMCCounterHalf(void);
void ETH_EnableMMCCounterFreeze(void);
void ETH_DisableMMCCounterFreeze(void);
void ETH_EnableMMCResetOnRead(void);
void ETH_DisableMMCResetOnRead(void);
void ETH_EnableMMCCounterRollover(void);
void ETH_DisableMMCCounterRollover(void);
void ETH_ResetMMCCounters(void);
void ETH_EnableMMCInterrupt(uint32_t interrupt);
void ETH_DisableMMCInterrupt(uint32_t interrupt);
uint8_t ETH_ReadMMCIntFlag(uint32_t flag);
uint32_t ETH_ReadMMCRegister(ETH_MMC_REG_T MMCReg);

/**@} end of group ETH_Fuctions*/
/**@} end of group ETH_Driver */
/**@} end of group Peripherals_Library*/

#ifdef __cplusplus
}
#endif

#endif /** __APM32F4xx_ETH_H */
